home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / python2.4 / profile.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2005-10-18  |  16KB  |  505 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.4)
  3.  
  4. '''Class for profiling Python code.'''
  5. import sys
  6. import os
  7. import time
  8. import marshal
  9. from optparse import OptionParser
  10. __all__ = [
  11.     'run',
  12.     'runctx',
  13.     'help',
  14.     'Profile']
  15.  
  16. def run(statement, filename = None, sort = -1):
  17.     '''Run statement under profiler optionally saving results in filename
  18.  
  19.     This function takes a single argument that can be passed to the
  20.     "exec" statement, and an optional file name.  In all cases this
  21.     routine attempts to "exec" its first argument and gather profiling
  22.     statistics from the execution. If no file name is present, then this
  23.     function automatically prints a simple profiling report, sorted by the
  24.     standard name string (file/line/function-name) that is presented in
  25.     each line.
  26.     '''
  27.     prof = Profile()
  28.     
  29.     try:
  30.         prof = prof.run(statement)
  31.     except SystemExit:
  32.         pass
  33.  
  34.     if filename is not None:
  35.         prof.dump_stats(filename)
  36.     else:
  37.         return prof.print_stats(sort)
  38.  
  39.  
  40. def runctx(statement, globals, locals, filename = None):
  41.     '''Run statement under profiler, supplying your own globals and locals,
  42.     optionally saving results in filename.
  43.  
  44.     statement and filename have the same semantics as profile.run
  45.     '''
  46.     prof = Profile()
  47.     
  48.     try:
  49.         prof = prof.runctx(statement, globals, locals)
  50.     except SystemExit:
  51.         pass
  52.  
  53.     if filename is not None:
  54.         prof.dump_stats(filename)
  55.     else:
  56.         return prof.print_stats()
  57.  
  58.  
  59. def help():
  60.     for dirname in sys.path:
  61.         fullname = os.path.join(dirname, 'profile.doc')
  62.         if os.path.exists(fullname):
  63.             sts = os.system('${PAGER-more} ' + fullname)
  64.             if sts:
  65.                 print '*** Pager exit status:', sts
  66.             
  67.             break
  68.             continue
  69.     else:
  70.         print 'Sorry, can\'t find the help file "profile.doc"', 'along the Python search path.'
  71.  
  72. if os.name == 'mac':
  73.     import MacOS
  74.     
  75.     def _get_time_mac(timer = MacOS.GetTicks):
  76.         return timer() / 60.0
  77.  
  78.  
  79. if hasattr(os, 'times'):
  80.     
  81.     def _get_time_times(timer = os.times):
  82.         t = timer()
  83.         return t[0] + t[1]
  84.  
  85.  
  86.  
  87. class Profile:
  88.     '''Profiler class.
  89.  
  90.     self.cur is always a tuple.  Each such tuple corresponds to a stack
  91.     frame that is currently active (self.cur[-2]).  The following are the
  92.     definitions of its members.  We use this external "parallel stack" to
  93.     avoid contaminating the program that we are profiling. (old profiler
  94.     used to write into the frames local dictionary!!) Derived classes
  95.     can change the definition of some entries, as long as they leave
  96.     [-2:] intact (frame and previous tuple).  In case an internal error is
  97.     detected, the -3 element is used as the function name.
  98.  
  99.     [ 0] = Time that needs to be charged to the parent frame\'s function.
  100.            It is used so that a function call will not have to access the
  101.            timing data for the parent frame.
  102.     [ 1] = Total time spent in this frame\'s function, excluding time in
  103.            subfunctions (this latter is tallied in cur[2]).
  104.     [ 2] = Total time spent in subfunctions, excluding time executing the
  105.            frame\'s function (this latter is tallied in cur[1]).
  106.     [-3] = Name of the function that corresponds to this frame.
  107.     [-2] = Actual frame that we correspond to (used to sync exception handling).
  108.     [-1] = Our parent 6-tuple (corresponds to frame.f_back).
  109.  
  110.     Timing data for each function is stored as a 5-tuple in the dictionary
  111.     self.timings[].  The index is always the name stored in self.cur[-3].
  112.     The following are the definitions of the members:
  113.  
  114.     [0] = The number of times this function was called, not counting direct
  115.           or indirect recursion,
  116.     [1] = Number of times this function appears on the stack, minus one
  117.     [2] = Total time spent internal to this function
  118.     [3] = Cumulative time that this function was present on the stack.  In
  119.           non-recursive functions, this is the total execution time from start
  120.           to finish of each invocation of a function, including time spent in
  121.           all subfunctions.
  122.     [4] = A dictionary indicating for each function name, the number of times
  123.           it was called by us.
  124.     '''
  125.     bias = 0
  126.     
  127.     def __init__(self, timer = None, bias = None):
  128.         self.timings = { }
  129.         self.cur = None
  130.         self.cmd = ''
  131.         self.c_func_name = ''
  132.         if bias is None:
  133.             bias = self.bias
  134.         
  135.         self.bias = bias
  136.         if timer is None:
  137.             if os.name == 'mac':
  138.                 self.timer = MacOS.GetTicks
  139.                 self.dispatcher = self.trace_dispatch_mac
  140.                 self.get_time = _get_time_mac
  141.             elif hasattr(time, 'clock'):
  142.                 self.timer = self.get_time = time.clock
  143.                 self.dispatcher = self.trace_dispatch_i
  144.             elif hasattr(os, 'times'):
  145.                 self.timer = os.times
  146.                 self.dispatcher = self.trace_dispatch
  147.                 self.get_time = _get_time_times
  148.             else:
  149.                 self.timer = self.get_time = time.time
  150.                 self.dispatcher = self.trace_dispatch_i
  151.         else:
  152.             self.timer = timer
  153.             t = self.timer()
  154.             
  155.             try:
  156.                 length = len(t)
  157.             except TypeError:
  158.                 self.get_time = timer
  159.                 self.dispatcher = self.trace_dispatch_i
  160.  
  161.             if length == 2:
  162.                 self.dispatcher = self.trace_dispatch
  163.             else:
  164.                 self.dispatcher = self.trace_dispatch_l
  165.             
  166.             def get_time_timer(timer = timer, sum = sum):
  167.                 return sum(timer())
  168.  
  169.             self.get_time = get_time_timer
  170.         self.t = self.get_time()
  171.         self.simulate_call('profiler')
  172.  
  173.     
  174.     def trace_dispatch(self, frame, event, arg):
  175.         timer = self.timer
  176.         t = timer()
  177.         t = t[0] + t[1] - self.t - self.bias
  178.         if event == 'c_call':
  179.             self.c_func_name = arg.__name__
  180.         
  181.         if self.dispatch[event](self, frame, t):
  182.             t = timer()
  183.             self.t = t[0] + t[1]
  184.         else:
  185.             r = timer()
  186.             self.t = r[0] + r[1] - t
  187.  
  188.     
  189.     def trace_dispatch_i(self, frame, event, arg):
  190.         timer = self.timer
  191.         t = timer() - self.t - self.bias
  192.         if event == 'c_call':
  193.             self.c_func_name = arg.__name__
  194.         
  195.         if self.dispatch[event](self, frame, t):
  196.             self.t = timer()
  197.         else:
  198.             self.t = timer() - t
  199.  
  200.     
  201.     def trace_dispatch_mac(self, frame, event, arg):
  202.         timer = self.timer
  203.         t = timer() / 60.0 - self.t - self.bias
  204.         if event == 'c_call':
  205.             self.c_func_name = arg.__name__
  206.         
  207.         if self.dispatch[event](self, frame, t):
  208.             self.t = timer() / 60.0
  209.         else:
  210.             self.t = timer() / 60.0 - t
  211.  
  212.     
  213.     def trace_dispatch_l(self, frame, event, arg):
  214.         get_time = self.get_time
  215.         t = get_time() - self.t - self.bias
  216.         if event == 'c_call':
  217.             self.c_func_name = arg.__name__
  218.         
  219.         if self.dispatch[event](self, frame, t):
  220.             self.t = get_time()
  221.         else:
  222.             self.t = get_time() - t
  223.  
  224.     
  225.     def trace_dispatch_exception(self, frame, t):
  226.         (rpt, rit, ret, rfn, rframe, rcur) = self.cur
  227.         if rframe is not frame and rcur:
  228.             return self.trace_dispatch_return(rframe, t)
  229.         
  230.         self.cur = (rpt, rit + t, ret, rfn, rframe, rcur)
  231.         return 1
  232.  
  233.     
  234.     def trace_dispatch_call(self, frame, t):
  235.         if self.cur and frame.f_back is not self.cur[-2]:
  236.             (rpt, rit, ret, rfn, rframe, rcur) = self.cur
  237.             if not isinstance(rframe, Profile.fake_frame):
  238.                 if not rframe.f_back is frame.f_back:
  239.                     raise AssertionError, ('Bad call', rfn, rframe, rframe.f_back, frame, frame.f_back)
  240.                 self.trace_dispatch_return(rframe, 0)
  241.                 if not self.cur is None and frame.f_back is self.cur[-2]:
  242.                     raise AssertionError, ('Bad call', self.cur[-3])
  243.             
  244.         
  245.         fcode = frame.f_code
  246.         fn = (fcode.co_filename, fcode.co_firstlineno, fcode.co_name)
  247.         self.cur = (t, 0, 0, fn, frame, self.cur)
  248.         timings = self.timings
  249.         if fn in timings:
  250.             (cc, ns, tt, ct, callers) = timings[fn]
  251.             timings[fn] = (cc, ns + 1, tt, ct, callers)
  252.         else:
  253.             timings[fn] = (0, 0, 0, 0, { })
  254.         return 1
  255.  
  256.     
  257.     def trace_dispatch_c_call(self, frame, t):
  258.         fn = ('', 0, self.c_func_name)
  259.         self.cur = (t, 0, 0, fn, frame, self.cur)
  260.         timings = self.timings
  261.         if timings.has_key(fn):
  262.             (cc, ns, tt, ct, callers) = timings[fn]
  263.             timings[fn] = (cc, ns + 1, tt, ct, callers)
  264.         else:
  265.             timings[fn] = (0, 0, 0, 0, { })
  266.         return 1
  267.  
  268.     
  269.     def trace_dispatch_return(self, frame, t):
  270.         if frame is not self.cur[-2]:
  271.             if not frame is self.cur[-2].f_back:
  272.                 raise AssertionError, ('Bad return', self.cur[-3])
  273.             self.trace_dispatch_return(self.cur[-2], 0)
  274.         
  275.         (rpt, rit, ret, rfn, frame, rcur) = self.cur
  276.         rit = rit + t
  277.         frame_total = rit + ret
  278.         (ppt, pit, pet, pfn, pframe, pcur) = rcur
  279.         self.cur = (ppt, pit + rpt, pet + frame_total, pfn, pframe, pcur)
  280.         timings = self.timings
  281.         (cc, ns, tt, ct, callers) = timings[rfn]
  282.         if not ns:
  283.             ct = ct + frame_total
  284.             cc = cc + 1
  285.         
  286.         if pfn in callers:
  287.             callers[pfn] = callers[pfn] + 1
  288.         else:
  289.             callers[pfn] = 1
  290.         timings[rfn] = (cc, ns - 1, tt + rit, ct, callers)
  291.         return 1
  292.  
  293.     dispatch = {
  294.         'call': trace_dispatch_call,
  295.         'exception': trace_dispatch_exception,
  296.         'return': trace_dispatch_return,
  297.         'c_call': trace_dispatch_c_call,
  298.         'c_exception': trace_dispatch_return,
  299.         'c_return': trace_dispatch_return }
  300.     
  301.     def set_cmd(self, cmd):
  302.         if self.cur[-1]:
  303.             return None
  304.         
  305.         self.cmd = cmd
  306.         self.simulate_call(cmd)
  307.  
  308.     
  309.     class fake_code:
  310.         
  311.         def __init__(self, filename, line, name):
  312.             self.co_filename = filename
  313.             self.co_line = line
  314.             self.co_name = name
  315.             self.co_firstlineno = 0
  316.  
  317.         
  318.         def __repr__(self):
  319.             return repr((self.co_filename, self.co_line, self.co_name))
  320.  
  321.  
  322.     
  323.     class fake_frame:
  324.         
  325.         def __init__(self, code, prior):
  326.             self.f_code = code
  327.             self.f_back = prior
  328.  
  329.  
  330.     
  331.     def simulate_call(self, name):
  332.         code = self.fake_code('profile', 0, name)
  333.         if self.cur:
  334.             pframe = self.cur[-2]
  335.         else:
  336.             pframe = None
  337.         frame = self.fake_frame(code, pframe)
  338.         self.dispatch['call'](self, frame, 0)
  339.  
  340.     
  341.     def simulate_cmd_complete(self):
  342.         get_time = self.get_time
  343.         t = get_time() - self.t
  344.         while self.cur[-1]:
  345.             self.dispatch['return'](self, self.cur[-2], t)
  346.             t = 0
  347.         self.t = get_time() - t
  348.  
  349.     
  350.     def print_stats(self, sort = -1):
  351.         import pstats as pstats
  352.         pstats.Stats(self).strip_dirs().sort_stats(sort).print_stats()
  353.  
  354.     
  355.     def dump_stats(self, file):
  356.         f = open(file, 'wb')
  357.         self.create_stats()
  358.         marshal.dump(self.stats, f)
  359.         f.close()
  360.  
  361.     
  362.     def create_stats(self):
  363.         self.simulate_cmd_complete()
  364.         self.snapshot_stats()
  365.  
  366.     
  367.     def snapshot_stats(self):
  368.         self.stats = { }
  369.         for cc, ns, tt, ct, callers in self.timings.iteritems():
  370.             callers = callers.copy()
  371.             nc = 0
  372.             for callcnt in callers.itervalues():
  373.                 nc += callcnt
  374.             
  375.             self.stats[func] = (cc, nc, tt, ct, callers)
  376.         
  377.  
  378.     
  379.     def run(self, cmd):
  380.         import __main__ as __main__
  381.         dict = __main__.__dict__
  382.         return self.runctx(cmd, dict, dict)
  383.  
  384.     
  385.     def runctx(self, cmd, globals, locals):
  386.         self.set_cmd(cmd)
  387.         sys.setprofile(self.dispatcher)
  388.         
  389.         try:
  390.             exec cmd in globals, locals
  391.         finally:
  392.             sys.setprofile(None)
  393.  
  394.         return self
  395.  
  396.     
  397.     def runcall(self, func, *args, **kw):
  398.         self.set_cmd(repr(func))
  399.         sys.setprofile(self.dispatcher)
  400.         
  401.         try:
  402.             return func(*args, **kw)
  403.         finally:
  404.             sys.setprofile(None)
  405.  
  406.  
  407.     
  408.     def calibrate(self, m, verbose = 0):
  409.         if self.__class__ is not Profile:
  410.             raise TypeError('Subclasses must override .calibrate().')
  411.         
  412.         saved_bias = self.bias
  413.         self.bias = 0
  414.         
  415.         try:
  416.             return self._calibrate_inner(m, verbose)
  417.         finally:
  418.             self.bias = saved_bias
  419.  
  420.  
  421.     
  422.     def _calibrate_inner(self, m, verbose):
  423.         get_time = self.get_time
  424.         
  425.         def f1(n):
  426.             for i in range(n):
  427.                 x = 1
  428.             
  429.  
  430.         
  431.         def f(m, f1 = f1):
  432.             for i in range(m):
  433.                 f1(100)
  434.             
  435.  
  436.         f(m)
  437.         t0 = get_time()
  438.         f(m)
  439.         t1 = get_time()
  440.         elapsed_noprofile = t1 - t0
  441.         if verbose:
  442.             print 'elapsed time without profiling =', elapsed_noprofile
  443.         
  444.         p = Profile()
  445.         t0 = get_time()
  446.         p.runctx('f(m)', globals(), locals())
  447.         t1 = get_time()
  448.         elapsed_profile = t1 - t0
  449.         if verbose:
  450.             print 'elapsed time with profiling =', elapsed_profile
  451.         
  452.         total_calls = 0.0
  453.         reported_time = 0.0
  454.         for filename, line, funcname in p.timings.items():
  455.             (cc, ns, tt, ct, callers) = None
  456.             if funcname in ('f', 'f1'):
  457.                 total_calls += cc
  458.                 reported_time += tt
  459.                 continue
  460.         
  461.         if verbose:
  462.             print "'CPU seconds' profiler reported =", reported_time
  463.             print 'total # calls =', total_calls
  464.         
  465.         if total_calls != m + 1:
  466.             raise ValueError('internal error: total calls = %d' % total_calls)
  467.         
  468.         mean = (reported_time - elapsed_noprofile) / 2.0 / total_calls
  469.         if verbose:
  470.             print 'mean stopwatch overhead per profile event =', mean
  471.         
  472.         return mean
  473.  
  474.  
  475.  
  476. def Stats(*args):
  477.     print 'Report generating functions are in the "pstats" module\x07'
  478.  
  479. if __name__ == '__main__':
  480.     usage = 'profile.py [-o output_file_path] [-s sort] scriptfile [arg] ...'
  481.     if not sys.argv[1:]:
  482.         print 'Usage: ', usage
  483.         sys.exit(2)
  484.     
  485.     
  486.     class ProfileParser(OptionParser):
  487.         
  488.         def __init__(self, usage):
  489.             OptionParser.__init__(self)
  490.             self.usage = usage
  491.  
  492.  
  493.     parser = ProfileParser(usage)
  494.     parser.allow_interspersed_args = False
  495.     parser.add_option('-o', '--outfile', dest = 'outfile', help = 'Save stats to <outfile>', default = None)
  496.     parser.add_option('-s', '--sort', dest = 'sort', help = 'Sort order when printing to stdout, based on pstats.Stats class', default = -1)
  497.     (options, args) = parser.parse_args()
  498.     sys.argv[:] = args
  499.     if len(sys.argv) > 0:
  500.         sys.path.insert(0, os.path.dirname(sys.argv[0]))
  501.         run('execfile(%r)' % (sys.argv[0],), options.outfile, options.sort)
  502.     else:
  503.         print 'Usage: ', usage
  504.  
  505.